package com.example.web.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * JedisUtil(推荐存Byte数组，存Json字符串效率更慢)
 * 
 * @author Wang926454
 * @date 2018/9/4 15:45
 */
@Component
public class JedisUtil {

	/**
	 * Logger
	 */

	/**
	 * Status-OK
	 */
	public final static String OK = "OK";

	/**
	 * 静态注入JedisPool连接池
	 * 本来是正常注入JedisUtil，可以在Controller和Service层使用，但是重写Shiro的CustomCache无法注入JedisUtil
	 * 现在改为静态注入JedisPool连接池，JedisUtil直接调用静态方法即可
	 * https://blog.csdn.net/W_Z_W_888/article/details/79979103
	 */
	private static JedisPool jedisPool;

	private static ShardedJedisPool shardedJedisPool;

	@Autowired
	public void setJedisPool(JedisPool jedisPool) {
		JedisUtil.jedisPool = jedisPool;
	}

	@Autowired
	public void setShardedJedisPool(ShardedJedisPool shardedJedisPool) {
		JedisUtil.shardedJedisPool = shardedJedisPool;
	}

	/**
	 * 获取Jedis实例
	 * 
	 * @param
	 * @return redis.clients.jedis.Jedis
	 * @author Wang926454
	 * @date 2018/9/4 15:47
	 */
	public static synchronized Jedis getJedis() {
		try {
			if (jedisPool != null) {
				Jedis resource = jedisPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("释放Jedis资源异常:" + e.getMessage());
		}
	}

	/**
	 * 获取shardedJedis实例
	 * 
	 * @return
	 */
	public static synchronized ShardedJedis getShardedJedis() {
		try {
			if (shardedJedisPool != null) {
				ShardedJedis resource = shardedJedisPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("释放ShardedJedis资源异常:" + e.getMessage());
		}
	}

	/**
	 * 释放Jedis资源
	 * 
	 * @param
	 * @return void
	 * @author Wang926454
	 * @date 2018/9/5 9:16
	 */
	public static void closePool() {
		try {
			jedisPool.close();
		} catch (Exception e) {
			throw new CustomException("释放Jedis资源异常:" + e.getMessage());
		}
	}

	/**
	 * 释放shardedJedis资源
	 * 
	 * @param jedis
	 */
	@SuppressWarnings("deprecation")
	public static void returnResource(final ShardedJedis shardedJedis) {
		if (shardedJedis != null) {
			shardedJedisPool.returnResource(shardedJedis);
		}
	}

	/**
	 * 获取redis键值-object
	 * 
	 * @param key
	 * @return java.lang.Object
	 * @author Wang926454
	 * @date 2018/9/4 15:47
	 */
	public static Object getObject(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			byte[] bytes = jedis.get(key.getBytes());
			if (StringUtil.isNotNull(bytes)) {
				return SerializableUtil.unserializable(bytes);
			}
		} catch (Exception e) {
			throw new CustomException("获取Redis键值getObject方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return null;
	}

	/**
	 * 设置redis键值-object
	 * 
	 * @param key
	 * @param value
	 * @return java.lang.String
	 * @author Wang926454
	 * @date 2018/9/4 15:49
	 */
	public static String setObject(String key, Object value) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.set(key.getBytes(), SerializableUtil.serializable(value));
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值setObject方法异常:key=" + key + " value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 设置redis键值-object-expiretime
	 * 
	 * @param key
	 * @param value
	 * @param expiretime
	 * @return java.lang.String
	 * @author Wang926454
	 * @date 2018/9/4 15:50
	 */
	public static String setObject(String key, Object value, int expiretime) {
		String result = "";
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.set(key.getBytes(), SerializableUtil.serializable(value));
			if (OK.equals(result)) {
				jedis.expire(key.getBytes(), expiretime);
			}
			return result;
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值setObject方法异常:key=" + key + " value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 获取redis键值-Json
	 * 
	 * @param key
	 * @return java.lang.Object
	 * @author Wang926454
	 * @date 2018/9/4 15:47
	 */
	public static String getJson(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.get(key);
		} catch (Exception e) {
			throw new CustomException("获取Redis键值getJson方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 设置redis键值-Json
	 * 
	 * @param key
	 * @param value
	 * @return java.lang.String
	 * @author Wang926454
	 * @date 2018/9/4 15:49
	 */
	public static String setJson(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.set(key, value);
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值setJson方法异常:key=" + key + " value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 设置redis键值-Json-expiretime
	 * 
	 * @param key
	 * @param value
	 * @param expiretime
	 * @return java.lang.String
	 * @author Wang926454
	 * @date 2018/9/4 15:50
	 */
	public static String setJson(String key, String value, int expiretime) {
		String result = "";
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.set(key, value);
			if (OK.equals(result)) {
				jedis.expire(key, expiretime);
			}
			return result;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值setJson方法异常:key=" + key + " value=" + value + "expiretime=" + expiretime
					+ " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 删除key
	 * 
	 * @param key
	 * @return java.lang.Long
	 * @author Wang926454
	 * @date 2018/9/4 15:50
	 */
	public static Long delKey(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.del(key.getBytes());
		} catch (Exception e) {
			throw new CustomException("删除Redis的键delKey方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * key是否存在
	 * 
	 * @param key
	 * @return java.lang.Boolean
	 * @author Wang926454
	 * @date 2018/9/4 15:51
	 */
	public static Boolean exists(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.exists(key.getBytes());
		} catch (Exception e) {
			throw new CustomException("查询Redis的键是否存在exists方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 模糊查询获取key集合
	 * 
	 * @param key
	 * @return java.util.Set<java.lang.String>
	 * @author Wang926454
	 * @date 2018/9/6 9:43
	 */
	public static Set<String> keysS(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.keys(key);
		} catch (Exception e) {
			throw new CustomException("模糊查询Redis的键集合keysS方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 模糊查询获取key集合
	 * 
	 * @param key
	 * @return java.util.Set<java.lang.String>
	 * @author Wang926454
	 * @date 2018/9/6 9:43
	 */
	public static Set<byte[]> keysB(String key) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			return jedis.keys(key.getBytes());
		} catch (Exception e) {
			throw new CustomException("模糊查询Redis的键集合keysB方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 获取过期剩余时间
	 * 
	 * @param key
	 * @return java.lang.String
	 * @author Wang926454
	 * @date 2018/9/11 16:26
	 */
	public static Long getExpireTime(String key) {
		Long result = -2L;
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.ttl(key);
			return result;
		} catch (Exception e) {
			throw new CustomException("获取Redis键过期剩余时间getExpireTime方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	// *******************key-value****************start

	/**
	 * 向缓存中设置对象
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static boolean set(String key, Object value) {
		Jedis jedis = null;
		try {
			String objectJson = JSON.toJSONString(value).toString();
			jedis = getJedis();
			if (jedis != null) {
				jedis.set(key, objectJson);
			}
			return true;
		} catch (Exception e) {
			throw new CustomException(
					"模糊查询Redis的键集合set方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 根据key 获取内容
	 * 
	 * @param key
	 * @return
	 */
	public static Object get(String key) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			Object value = jedis.get(key);
			return value;
		} catch (Exception e) {
			throw new CustomException("获取Redis键过期剩余时间get方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 根据key 获取对象
	 * 
	 * @param key
	 * @return
	 */
	public static <T> T get(String key, Class<T> clazz) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				return (T) JSON.parseObject(JSON.toJSONString(jedis.get(key)), clazz);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("模糊查询Redis的键集合get方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	// *******************key-value****************end

	// *************** 操作list****************start
	/**
	 * 向缓存中设置对象
	 * 
	 * @param key
	 * @param list T string calss
	 * @return
	 */
	public static <T> boolean setList(String key, List<T> list) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			if (jedis != null) {
				for (T vz : list) {
					if (vz instanceof String) {
						jedis.lpush(key, (String) vz);
					} else {
						String objectJson = JSON.toJSONString(vz).toString();
						jedis.lpush(key, objectJson);
					}
				}
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw new CustomException(
					"模糊查询Redis的键集合setList方法异常:key=" + key + "list=" + list + "cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static <T> List<T> getListEntity(String key, Class<T> entityClass) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				List<String> valueJson = jedis.lrange(key, 0, -1);
				return (List<T>) JSON.parseArray(JSON.parse((valueJson).toString()).toString(), entityClass);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("模糊查询Redis的键集合getListEntity方法异常:key=" + key + "cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static List<String> getListString(String key) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				return jedis.lrange(key, 0, -1);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("模糊查询Redis的键集合getListString方法异常:key=" + key + "cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// *************** 操作list****************end
	// *************** 操作map****************start
	public static <K, V> boolean setMap(String key, Map<String, V> map) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			if (jedis != null) {
				Set<Map.Entry<String, V>> entry = map.entrySet();
				for (Iterator<Map.Entry<String, V>> ite = entry.iterator(); ite.hasNext();) {
					Map.Entry<String, V> kv = ite.next();
					if (kv.getValue() instanceof String) {
						jedis.hset(key, kv.getKey(), (String) kv.getValue());
					} else if (kv.getValue() instanceof List) {
						jedis.hset(key, kv.getKey(), JSON.toJSONString(kv.getValue()).toString());
					} else {
						jedis.hset(key, kv.getKey(), JSON.toJSONString(kv.getValue()).toString());
					}
				}
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值setMap方法异常:key=" + key + " map=" + map + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static boolean setMapKey(String key, String mapKey, Object value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			if (jedis != null) {
				if (value instanceof String) {
					jedis.hset(key, mapKey, String.valueOf(value));
				} else if (value instanceof List) {
					jedis.hset(key, mapKey, JSON.toJSONString(value).toString());
				} else {
					jedis.hset(key, mapKey, JSON.toJSONString(value).toString());
				}
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值setMapKey方法异常:key=" + key + "mapKey=" + mapKey + " value=" + value
					+ " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * seconds key和value 保存的有效时间（单位：秒）
	 * 
	 * @return
	 */
	public static boolean setMapKeyExpire(String key, String mapKey, Object value, int seconds) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			if (jedis != null) {
				if (value instanceof String) {
					jedis.hset(key, mapKey, String.valueOf(value));
				} else if (value instanceof List) {
					jedis.hset(key, mapKey, JSON.toJSONString(value).toString());
				} else {
					jedis.hset(key, mapKey, JSON.toJSONString(value).toString());
				}
				jedis.expire(key, seconds);
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值setMapKeyExpire方法异常:key=" + key + "mapKey=" + mapKey + " value=" + value
					+ " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	@SuppressWarnings("unchecked")
	public static <K, V> Map<String, V> getMap(String key) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				Map<String, V> map = (Map<String, V>) jedis.hgetAll(key);
				return map;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值getMap方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	/**
	 *	存：Map<key, Map<mapkey,单个对象>>
	 * 	取：Map<key,单个对象>
	 * @param key
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<String, V> getMapEntityClass(String key, Class<V> clazz) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				Map<String, V> map = (Map<String, V>) jedis.hgetAll(key);
				Set<Map.Entry<String, V>> entry = map.entrySet();
				for (Iterator<Map.Entry<String, V>> ite = entry.iterator(); ite.hasNext();) {
					Map.Entry<String, V> kv = ite.next();
					map.put(kv.getKey(),
							(V) JSON.parseObject(JSON.parse(JSON.toJSONString(kv.getValue())).toString(), clazz));
				}
				return map;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值getMapEntityClass方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	/**
	 * 存：Map<key, Map<mapkey,单个对象>>
	 * 取：Map<Key,List<V>>
	 * @param key
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<String, List<V>> getMapListEntityClass(String key, Class<V> clazz) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				Map<String, V> map = (Map<String, V>) jedis.hgetAll(key);
				Set<Map.Entry<String, V>> entry = map.entrySet();
				Map<String, List<V>> maplist = new  HashMap<String, List<V>>();
				List<V> list = new ArrayList<V>();
				for (Iterator<Map.Entry<String, V>> ite = entry.iterator(); ite.hasNext();) {
					Map.Entry<String, V> kv = ite.next();
					list.add((V) JSON.parseObject(JSON.parse(JSON.toJSONString(kv.getValue())).toString(), clazz));
					maplist.put(key,list);
				}
				return maplist;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值getMapEntityClass方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	
	/**
	 * Map<String,Map<mapkey,List<v>>>	
	 * @param key
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<String, List<V>> getMapList(String key, Class<V> clazz) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				Map<String, V> map = (Map<String, V>) jedis.hgetAll(key);
				Set<Map.Entry<String, V>> entry = map.entrySet();
				for (Iterator<Map.Entry<String, V>> ite = entry.iterator(); ite.hasNext();) {
					Map.Entry<String, V> kv = ite.next();
					map.put(kv.getKey(),
							(V) JSON.parseArray(JSON.parse(JSON.toJSONString(kv.getValue())).toString(), clazz));
				}
				return (Map<String, List<V>>) map;
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException("设置Redis键值getMapList方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static <T> List<T> getMapKeyListEntity(String key, String mapKey, Class<T> entityClass) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				String valueJson = jedis.hget(key, mapKey);
				return (List<T>) JSON.parseArray(valueJson, entityClass);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值getMapKeyListEntity方法异常:key=" + key + "mapKey=" + mapKey + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static <T> T getMapKeyEntity(String key, String mapKey, Class<T> entityClass) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				String valueJson = jedis.hget(key, mapKey);
				return (T) JSON.parseObject(valueJson, entityClass);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值getMapKeyEntity方法异常:key=" + key + "mapKey=" + mapKey + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static Object getMapKey(String key, String mapKey) {
		ShardedJedis jedis = null;
		try {
			jedis = getShardedJedis();
			if (jedis != null) {
				return jedis.hget(key, mapKey);
			} else {
				return null;
			}
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值getMapKey方法异常:key=" + key + "mapKey=" + mapKey + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static boolean delMapKey(String key, String mapKey) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.hdel(key, mapKey);
			return true;
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值delMapKey方法异常:key=" + key + "mapKey=" + mapKey + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	public static boolean hexists(String key, String mapKey) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			return jedis.hexists(key, mapKey);
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值hexists方法异常:key=" + key + "mapKey=" + mapKey + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}
	// *************** 操作map****************end
	// ***************计数器应用INCR,DECR****************begin
	// Redis的命令都是原子性的，你可以轻松地利用INCR，DECR命令来构建计数器系统

	/**
	 * incr(key)：名称为key的string增1操作
	 */
	public static boolean incr(String key) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.incr(key);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值incr方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * incrby(key, integer)：名称为key的string增加integer
	 */
	public static boolean incrBy(String key, int value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.incrBy(key, value);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值incrBy方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * decr(key)：名称为key的string减1操作
	 */
	public static boolean decr(String key) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.decr(key);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值decr方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * decrby(key, integer)：名称为key的string减少integer
	 */
	public static boolean decrBy(String key, int value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.decrBy(key, value);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值decrBy方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// ***************计数器应用INCR,DECR****************end
	// ***************使用sorted set(zset)甚至可以构建有优先级的队列系统***************begin
	/**
	 * 向名称为key的zset中添加元素member，score用于排序。 如果该元素已经存在，则根据score更新该元素的顺序
	 */
	public static boolean zadd(String key, double score, String member) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.zadd(key, score, member);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zadd方法异常:key=" + key + "score=" + score + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 删除名称为key的zset中的元素member
	 */
	public static boolean zrem(String key, String... members) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.zrem(key, members);
			return true;
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值zrem方法异常:key=" + key + "members=" + members + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * 返回集合中score在给定区间的元素
	 */
	public static Set<String> zrangeByScore(String key, double min, double max) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			return jedis.zrangeByScore(key, min, max);
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值zrangeByScore方法异常:key=" + key + "min=" + min + "max=" + max + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// ***************使用sorted set(zset)甚至可以构建有优先级的队列系统***************end
	// ***************sorted set 处理***************************************begin
	// zset 处理
	public static boolean zaddObject(String key, double score, Object value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			String objectJson = JSON.toJSONString(value).toString();
			jedis.zadd(key, score, objectJson);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zaddObject方法异常:key=" + key + "score=" + score + "value=" + value
					+ " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * score值递减(从大到小)次序排列。
	 * 
	 * @param key
	 * @param max         score
	 * @param min         score
	 * @param entityClass
	 * @return
	 */
	public static <T> List<T> zrevrangeByScore(String key, double max, double min, Class<T> entityClass) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			Set<String> set = jedis.zrevrangeByScore(key, max, min);
			List<T> list = new ArrayList<T>();
			for (String str : set) {
				list.add((T) JSON.parseObject(JSON.toJSONString(str), entityClass));
			}
			return list;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zrevrangeByScore方法异常:key=" + key + "max=" + max + "min=" + min
					+ " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * score值递减(从大到小)次序排列。
	 * 
	 * @param key
	 * @param max         score
	 * @param min         score
	 * @param offset      count (类似mysql的 LIMIT)
	 * @param entityClass
	 * @return
	 */
	public static <T> List<T> zrevrangeByScore(String key, double max, double min, int offset, int count,
			Class<T> entityClass) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			Set<String> set = jedis.zrevrangeByScore(key, max, min, offset, count);
			List<T> list = new ArrayList<T>();
			for (String str : set) {
				list.add((T) JSON.parseObject(JSON.toJSONString(str), entityClass));
			}
			return list;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zrevrangeByScore方法异常:key=" + key + "max=" + max + "min=" + min
					+ "offset=" + offset + "count=" + count + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// 得到总记录数
	public static long zcard(String key) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			return jedis.zcard(key);
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zcard方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// 删除 元素
	public static boolean zremObject(String key, Object value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			String objectJson = JSON.toJSONString(value).toString();
			jedis.zrem(key, objectJson);
			return true;
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值zremObject方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// 统计zset集合中score某个范围内（1-5），元素的个数
	public static long zcount(String key, double min, double max) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			return jedis.zcount(key, min, max);
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值zcount方法异常:key=" + key + "min=" + min + "max=" + max + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// 查看zset集合中元素的score
	public static double zscore(String key, Object value) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			String objectJson = JSON.toJSONString(value).toString();
			return jedis.zscore(key, objectJson);
		} catch (Exception e) {
			throw new CustomException("设置Redis键值zscore方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	// **************sorted set******************************************end
	// ***********************Redis Set集合操作**************************begin
	/**
	 * sadd:向名称为Key的set中添加元素,同一集合中不能出现相同的元素值。（用法：sadd set集合名称 元素值）
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static boolean sadd(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.sadd(key, value);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值sadd方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * srem:删除名称为key的set中的元素。（用法：srem set集合名称 要删除的元素值）
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static boolean srem(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = getJedis();
			jedis.srem(key, value);
			return true;
		} catch (Exception e) {
			throw new CustomException("设置Redis键值srem方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * sdiff:返回所有给定key与第一个key的差集。（用法：sdiff set集合1 set集合2）
	 * 
	 * @param key1
	 * @param key2
	 * @return
	 */
	public static Set<String> sdiff(String key1, String key2) {
		Jedis jedis = null;
		Set<String> diffList = null;
		try {
			jedis = getJedis();
			diffList = jedis.sdiff(key1, key2);
		} catch (Exception e) {
			throw new CustomException("设置Redis键值sdiff方法异常:key1=" + key1 + "key2=" + key2 + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return diffList;
	}

	/**
	 * sismember:判断某个值是否是集合的元素。（用法：sismember 集合1 指定的元素值）
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public static boolean sismember(String key, String value) {
		ShardedJedis jedis = null;
		try {
			jedis = shardedJedisPool.getResource();
			return jedis.sismember(key, value);
		} catch (Exception e) {
			throw new CustomException(
					"设置Redis键值sismember方法异常:key=" + key + "value=" + value + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
	}

	/**
	 * smembers(key) ：返回名称为key的set的所有元素
	 * 
	 * @param key
	 * @return
	 */
	public static Set<String> smembers(String key) {
		Jedis jedis = null;
		Set<String> list = null;
		try {
			jedis = getJedis();
			list = jedis.smembers(key);
		} catch (Exception e) {
			throw new CustomException("设置Redis键值smembers方法异常:key=" + key + " cause=" + e.getMessage());
		} finally {
			if (jedis != null) {
				jedis.close();
			}
		}
		return list;
	}

	// ***********************Redis Set集合操作****************************end
}
